﻿using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using LayoutViewer.Views;
using Newtonsoft.Json;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LayoutViewer.Models.Helpers
{
    class ATHelper : IHelper
    {
        public string Path { get; } = "AT连接";
        public string Name { get; } = "AT连接";
        public Action<Bitmap, MoveCategory>? SuccessCallBack { get; set; }
        public Action<string>? FailCallBack { get; set; }

        public string LocalIP { get; set; } = string.Empty;

        public string RemoteIP { get; set; } = string.Empty;

        private TcpClient? Client;

        private string deviceName = "null";

        public ATHelper(string localIP, string remoteIP)
        {
            this.LocalIP = localIP;
            this.RemoteIP = remoteIP;

            Initialize();
        }

        public async void Initialize()
        {
            await Task.Run(() =>
            {
                try
                {
                    this.Client = new TcpClient(this.RemoteIP, 1024);
                    ConnectAsync(this.Client);
                }
                catch (Exception ex)
                {
                    MessageBox.ShowAsync(ex.ToString());
                }
            });
        }


        private void ConnectAsync(TcpClient client)
        {
            _ = Task.Run(async () =>
            {
                var stream = client.GetStream();
                while (true)
                {
                    try
                    {
                        Thread.Sleep(50);
                        var data = await Stick.ReadPackAsync(stream);

                        switch (data.Key)
                        {
                            case "init":
                            {
                                this.deviceName = data.Description;
                                break;
                            }
                            case "LayoutDump_success":
                            {
                                using var ms = new MemoryStream(data.Buffer);
                                var imgLen = ms.ReadInt32();
                                var imgBytes = new byte[imgLen];
                                ms.Read(imgBytes);
                                var jsLen = ms.ReadInt32();
                                var jsBytes = new byte[jsLen];
                                ms.Read(jsBytes);

                                var sKBitmap = SKBitmap.Decode(imgBytes);
                                var pxFormat = sKBitmap.ColorType == SKColorType.Rgba8888 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888;
                                var bitmap = new Bitmap(pxFormat, AlphaFormat.Opaque, sKBitmap.GetPixels(), new PixelSize(sKBitmap.Width, sKBitmap.Height), new Vector(96, 96), sKBitmap.RowBytes);

                                var js = Encoding.UTF8.GetString(jsBytes);
                                var layoutInfo = JsonConvert.DeserializeObject<MoveCategory>(js);

                                if (bitmap is not null && layoutInfo is not null)
                                {
                                    this.SuccessCallBack?.Invoke(bitmap, layoutInfo);
                                }
                                break;
                            }
                            case "LayoutDump_fail":
                            {
                                this.FailCallBack?.Invoke(data.Description);
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        this.FailCallBack?.Invoke(ex.ToString());
                        return;
                    }
                }
            });
        }

        public async Task<ObservableCollection<string>> List()
        {
            return await Task.Run(() =>
            {
                var result = new ObservableCollection<string>
                {
                     this.deviceName
                };
                return result;
            });
        }

        public void LayoutDump(int Index)
        {
            if (this.Client == null) throw new Exception("tcp未连接!");
            if (!this.Client.Connected) throw new Exception("tcp已断开连接");

            try
            {
                var stream = this.Client.GetStream();
                var pack = Stick.MakePackData("layoutDump");
                stream.Write(pack);
            }
            catch (Exception ex)
            {
                MessageBox.ShowAsync(ex.Message);
            }
        }

        public void Dispose()
        {
            try
            {
                this.Client?.Close();
                this.Client?.Dispose();
                GC.SuppressFinalize(this);
            }
            catch { };
        }
    }
}
